package com.heima.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.admin.dto.LoginDto;
import com.heima.article.entity.ApAuthor;
import com.heima.article.feign.ArticleFeign;
import com.heima.common.dto.ResponseResult;
import com.heima.common.dto.User;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.enums.UserEnum;
import com.heima.common.util.AppJwtUtil;
import com.heima.common.util.UserThreadLocalUtil;
import com.heima.media.entity.WmUser;
import com.heima.user.dto.FollowBehaviorDto;
import com.heima.user.dto.UserRelationDto;
import com.heima.user.entity.ApUser;
import com.heima.user.entity.ApUserFollow;
import com.heima.user.mapper.ApUserMapper;
import com.heima.user.service.IApUserFollowService;
import com.heima.user.service.IApUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * APP用户信息表 服务实现类
 * </p>
 *
 * @author itheima
 * @since 2021-12-22
 */
@Service
public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements IApUserService {

    @Autowired
    private ArticleFeign articleFeign;

    @Autowired
    private IApUserFollowService userFollowService;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Value("${topic.followBehaviorTopic}")
    public String followBehaviorTopic;


    /**
     * APP端用户登录
     *
     * @param dto 入参中可能提交手机号密码登录或者提交设备ID（先看看）
     * @return jwt令牌
     */
    @Override
    public ResponseResult login(LoginDto dto) {
        //1.校验入参必填项
        if (dto == null || (StringUtils.isBlank(dto.getPhone()) && StringUtils.isBlank(dto.getPassword()) && StringUtils.isBlank(dto.getEquipmentId()))) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2. 判断手机号和密码是否为空，都有值 使用手机号跟密码进行登录
        //2.1 根据账户查询自媒体用户信息
        if (StringUtils.isNotBlank(dto.getPhone()) && StringUtils.isNotBlank(dto.getPassword())) {
            LambdaQueryWrapper<ApUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ApUser::getPhone, dto.getPhone());
            ApUser one = this.getOne(queryWrapper);
            if (one == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
            }

            //3.校验用户填写密码是否正确
            //3.1 将入参中用户填写密码+盐进行MD5加密 得到 密文
            String pwdStr = dto.getPassword() + one.getSalt();
            String userEnterPwdEncodedStr = DigestUtils.md5DigestAsHex(pwdStr.getBytes());
            //3.2 从用户记录中获取正确密码 跟 上一步得到密文进行比较
            if (!one.getPassword().equals(userEnterPwdEncodedStr)) {
                return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
            }

            //4.认证通过后，基于JWT生成用户令牌,载荷中需要两个属性 userId userName
            Map<String, Object> claimMaps = new HashMap<>();
            claimMaps.put("userId", one.getId());
            claimMaps.put("userName", one.getName());
            String token = AppJwtUtil.getToken(claimMaps);

            //5.封装响应数据（user,token） 其中用户信息中敏感数据要做脱敏处理
            //5.1 对返回用户信息做脱敏处理
            one.setSalt(null);
            one.setPhone(null);
            one.setPassword(null);
            //5.2 响应结果对象
            HashMap<String, Object> mapResult = new HashMap<>();
            mapResult.put("user", one);
            mapResult.put("token", token);
            return ResponseResult.okResult(mapResult);
        }


        //6. 用户点击“先看看” 使用设备ID进行登录 约定：JWT载荷中用户ID 设置为0
        if (StringUtils.isNotBlank(dto.getEquipmentId())) {
            //6.1 设置用户载荷信息
            HashMap<String, Object> claims = new HashMap<>();
            claims.put("userId", 0);
            String token = AppJwtUtil.getToken(claims);

            //6.2 响应结果对象
            HashMap<String, Object> mapResult = new HashMap<>();
            mapResult.put("token", token);
            return ResponseResult.okResult(mapResult);
        }

        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);

    }

    /**
     * 登录用户关注/取消关注某个自媒体作者
     *
     * @param dto 文档ID，作者ID，操作类型，设备ID
     * @return
     */
    @Override
    public ResponseResult follow(UserRelationDto dto) {
        //1.从ThreadLocal中获取登录用户信息
        User user = UserThreadLocalUtil.get();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2.构建用户关注实体类PO对象
        ApUserFollow apUserFollow = new ApUserFollow();
        //2.1 设置当前登录用户信息
        apUserFollow.setUserId(user.getUserId());
        apUserFollow.setUserName(user.getUserName());

        //2.2 设置关注目标用户信息
        //2.2.1 远程调用文章微服务得到作者信息
        ResponseResult<ApAuthor> responseResult = articleFeign.getAuthorById(dto.getAuthorId());
        if (responseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
            ApAuthor apAuthor = responseResult.getData();
            apUserFollow.setFollowId(apAuthor.getUserId());
            apUserFollow.setFollowName(apAuthor.getName());
            apUserFollow.setLevel(UserEnum.USER_FOLLOW_LEVEL_ONCE.getVal());

            //3.根据用户操作类型 新增关注记录或者删除关注记录
            LambdaQueryWrapper<ApUserFollow> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ApUserFollow::getUserId, user.getUserId());
            queryWrapper.eq(ApUserFollow::getFollowId, apAuthor.getUserId());
            //3.1 判断用户操作动作：关注还是取消关注
            Integer operation = dto.getOperation();
            if (operation.equals(UserEnum.USER_FOLLOW_OPRATION.getVal())) {
                //3.1.1关注
                ApUserFollow follow = userFollowService.getOne(queryWrapper);
                if (follow == null) {
                    //第一次关注，直接保存
                    userFollowService.save(apUserFollow);
                }
            } else {
                //3.1.2 取消关注
                userFollowService.remove(queryWrapper);
            }
            //4.TODO 发送消息到Kafka中，将来行为微服务作为监听器获取行为数据
            FollowBehaviorDto followBehaviorDto = new FollowBehaviorDto();
            followBehaviorDto.setUserId(user.getUserId());
            followBehaviorDto.setFollowId(apAuthor.getUserId());
            followBehaviorDto.setEquipmentId(dto.getEquipmentId());
            followBehaviorDto.setOperation(dto.getOperation());
            kafkaTemplate.send(followBehaviorTopic, JSON.toJSONString(followBehaviorDto));
        }
        return ResponseResult.okResult();
    }
}
